using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading.Tasks;

namespace SharpSoft.Net.WebSockets
{
    public class WebSocketServer : IDisposable
    {
        HttpListener httpListener;
        int maxClientCount = 200;//最大接受的客户端数量
        int maxMsgLength = 1024 * 1024;//单个消息最大长度
        List<HttpListenerWebSocketContext> clients = new List<HttpListenerWebSocketContext>(20);
        public WebSocketServer(string url, int port, int maxmsglength = 1024 * 1024, int maxclientcount = 200)
        {
            httpListener = new HttpListener();
            if (string.IsNullOrEmpty(url))
            {//*********注意：此处使用通配符+需要管理员权限********
#if DEBUG//调试时使用127.0.0.1
                httpListener.Prefixes.Add($"http://127.0.0.1:{port}/");
#else
                
                httpListener.Prefixes.Add($"http://+:{port}/"); 
#endif

            }
            else
            {
                httpListener.Prefixes.Add($"http://{url}:{port}/");
            }

        }

        private async void acceptWhile()
        {
            while (httpListener.IsListening)
            {
                try
                {
                    var hlc = await httpListener.GetContextAsync();
                    var wsc = await hlc.AcceptWebSocketAsync(null);
                    try
                    {
                        appendClient(wsc);
                    }
                    catch (Exception ex)
                    {
                        StreamWriter sw = new StreamWriter(hlc.Response.OutputStream);
                        sw.WriteLine(ex.Message);
                    }
                    receive(wsc);
                }
                catch (Exception ex)
                {
#if DEBUG
                    Console.WriteLine(ex);
#endif
                }


            }
        }



        private async void receive(HttpListenerWebSocketContext client)
        {
            byte[] buf = new byte[maxMsgLength];
            while (client.WebSocket.State == WebSocketState.Open)
            {
                ArraySegment<byte> seg = new ArraySegment<byte>(buf);
                var result = await client.WebSocket.ReceiveAsync(seg, new System.Threading.CancellationToken(false));
                if (result.MessageType == WebSocketMessageType.Close)
                {
                    await client.WebSocket.CloseAsync(WebSocketCloseStatus.Empty, "客户端请求正常关闭", new System.Threading.CancellationToken());
                    return;
                }
                var data = new byte[result.Count];
                Array.Copy(buf, 0, data, 0, data.Length);
                MessageReceived?.Invoke(client, result, data);
            }

        }
        /// <summary>
        /// 在收到消息时触发
        /// </summary>
        public event MessageReceivedEventHandler MessageReceived;

        private void appendClient(HttpListenerWebSocketContext client)
        {
            if (clients.Count >= maxClientCount)
            {//超出最大连接数
                throw new Exception("Exceeds the maximum allowable number of connections.");
            }
            clients.Add(client);

        }

        public void Dispose()
        {
            this.Close();
        }

        #region 控制

        public void Close()
        {
            httpListener.Close();
        }

        public void Start()
        {
            httpListener.Start();
            acceptWhile();
        }

        public void Stop()
        {
            httpListener.Close();
        }
        #endregion

        public delegate void MessageReceivedEventHandler(HttpListenerWebSocketContext client, WebSocketReceiveResult result, byte[] data);
    }
}
